/**
* @author Eugenia Jose
* @author Fernando Turon
* @version 1.0 17-04-12
*
* La clase GestorBBDD corresponde a la capa de negocio y se instancia en distintas parte de la aplicacion.
* Se usa para la gestión de la conexión y desconexión de la base de datos
* y para la gestión de las sentencias necesarias para los accesos a la misma.
*
*/
package edu.uoc.tds.pec4.server.bbdd;

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;
import java.sql.Statement;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.util.Properties;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;

import javax.swing.JOptionPane;

import edu.uoc.tds.pec4.i18n.GestorIdiomas;

public class GestorBBDD {
    /** ConExión de la BBDD. */
    private Connection conexion;
    /** dirección del fichero de propiedades. */
    final String propertiesFile = new File(".").getAbsolutePath() + "/properties/configuration.properties";
    /** DRiver de conexión. */
    final String driver = "org.postgresql.Driver";
    /** variable para indicar si se esta conectad o no. */
    private boolean conectado = false;
    /** sentencia a ejecutar. */
    private Statement sentencia = null;

    /**
     * Método para obtener una instancia de Connection
     * {pre: una conexión a BBDDD)
     * {post: una instancia de Connection}
     */
    public Connection getConexion(){
        return this.conexion;
    }

    /**
     * Método para establecer la conexión e indicar si existe conexión
     * {pre: una conexión a BBDDD)
     * {post: un booleano que indica si se está conectado y }
     */
    public boolean conectaBD() {
        String url;
        String schema;
        String usuario;
        String clave;
        
        try {
            if (!conectado){
                //Recoger el driver JDBC especifico de Postgre
                Class.forName(driver);
                //Recuperar información del fichero de propiedades
                Properties prop = new Properties();
                prop.load(new FileInputStream(propertiesFile));

                url = prop.getProperty("url");
                schema = prop.getProperty("schema");
                usuario = prop.getProperty("username");
                clave = prop.getProperty("password");

                this.conexion = DriverManager.getConnection(url, usuario, clave);
                this.conectado = true;
            }
        }

        /** Capturamos el error en que el caso que no se encuentre una clase, en este caso el driver JDBC*/
        catch (ClassNotFoundException exc) {
            System.out.println(exc.getMessage());
            JOptionPane.showMessageDialog(null, GestorIdiomas.getMessage("error.gestorbbdd.driver.jdbc"), GestorIdiomas.getMessage("error"), JOptionPane.ERROR_MESSAGE);
        }
        
        /** Capturamos el error en que el caso de que el fichero de propiedades no exista */
        catch (FileNotFoundException exc) {
            System.out.println(exc.getMessage());
            JOptionPane.showMessageDialog(null, GestorIdiomas.getMessage("error.gestorbbdd.no.fichero.properties"), GestorIdiomas.getMessage("error"), JOptionPane.ERROR_MESSAGE);
        }

        /** Capturamos el error en el caso de acceso IO */
        catch (IOException exc) {
            System.out.println(exc.getMessage());
            JOptionPane.showMessageDialog(null, GestorIdiomas.getMessage("error.gestorbbdd.fichero.properties"), GestorIdiomas.getMessage("error"), JOptionPane.ERROR_MESSAGE);
        }

        /** Capturamos el error en el acceso a la BBDD */
        catch (SQLException exc) {
            System.out.println(exc.getMessage());
            JOptionPane.showMessageDialog(null, GestorIdiomas.getMessage("error.gestorbbdd.bbdd"), GestorIdiomas.getMessage("error"), JOptionPane.ERROR_MESSAGE);
        }

        /** Capturamos excepción de carácter general*/
        catch (Exception exc) {
            System.out.println(exc.getMessage());
            JOptionPane.showMessageDialog(null, GestorIdiomas.getMessage("error.general"), GestorIdiomas.getMessage("error"), JOptionPane.ERROR_MESSAGE);
        }

        return conectado;
    }

    /**
     * Método para desconectar e indicar si se ha realizado la acción correctamente
     * {pre: una conexión a BBDDD)
     * {post: un booleano que indica si NO se está conectado y }
     */
    public boolean desconectaBD() {
        boolean desconexionRealizada = false;
        try {
            if (conectado){
                this.conexion.close();
                conectado = false;
                desconexionRealizada = true;
            }
        }
        
        /** Capturamos el error en el acceso a la BBDD */
        catch (SQLException exc) {
            JOptionPane.showMessageDialog(null, GestorIdiomas.getMessage("error.gestorbbdd.bbdd"), GestorIdiomas.getMessage("error"), JOptionPane.ERROR_MESSAGE);
        }

        /** Capturamos excepción de carácter general*/
        catch (Exception exc) {
            JOptionPane.showMessageDialog(null, GestorIdiomas.getMessage("error.general"), GestorIdiomas.getMessage("error"), JOptionPane.ERROR_MESSAGE);
        }
        
        return desconexionRealizada;
    }

    /**
     * Método para crear una instancia que crea un objeto de tipo Statement
     * {pre: una conexión a BBDDD)
     * {post: un objeto de tipo Statement }
     */
    public Statement crearSentencia(){
        Statement sentencia = null;
        try{
            sentencia = this.conexion.createStatement();
        }

        /** Capturamos el error en el acceso a la BBDD */
        catch (SQLException exc) {
            JOptionPane.showMessageDialog(null, GestorIdiomas.getMessage("error.gestorbbdd.bbdd"), GestorIdiomas.getMessage("error"), JOptionPane.ERROR_MESSAGE);
        }

        /** Capturamos excepción de carácter general*/
        catch (Exception exc) {
            JOptionPane.showMessageDialog(null, GestorIdiomas.getMessage("error.general"), GestorIdiomas.getMessage("error"), JOptionPane.ERROR_MESSAGE);
        }

        return sentencia;
    }

    /**
     * Método para crear una instancia que CIERRA un objeto de tipo Statement
     * {pre: un instancia de tipo STatement creada)
     * {post: es un método que no devuelve parámetros}
     */
    public void cerrarSentencia(){
        try{
            sentencia.close(); //cierra la sentencia
        }

        /** Capturamos el error en el acceso a la BBDD */
        catch (SQLException exc) {
            JOptionPane.showMessageDialog(null, GestorIdiomas.getMessage("error.gestorbbdd.bbdd"), GestorIdiomas.getMessage("error"), JOptionPane.ERROR_MESSAGE);
        }

        /** Capturamos excepción de carácter general*/
        catch (Exception exc) {
            JOptionPane.showMessageDialog(null, GestorIdiomas.getMessage("error.general"), GestorIdiomas.getMessage("error"), JOptionPane.ERROR_MESSAGE);
        }
    }

    /**
     * Método para crear una instancia que crea un objeto de tipo PreparedStatement
     * {pre: un instancia de tipo Statement creada)
     * {post: devuelve una instancia de PreparedStatement
     *   que se utiliza para ejecutar código evitando ataques de SQLInjection}
     */
    public PreparedStatement prepararSentencia(String statement){
        PreparedStatement preparedStatement = null;
        
        try{
            preparedStatement = conexion.prepareStatement(statement, ResultSet.TYPE_SCROLL_INSENSITIVE, ResultSet.CONCUR_UPDATABLE);
        }

        /** Capturamos el error en el acceso a la BBDD */
        catch (SQLException exc) {
            JOptionPane.showMessageDialog(null, GestorIdiomas.getMessage("error.gestorbbdd.bbdd"), GestorIdiomas.getMessage("error"), JOptionPane.ERROR_MESSAGE);
        }

        /** Capturamos excepción de carácter general*/
        catch (Exception exc) {
            JOptionPane.showMessageDialog(null, GestorIdiomas.getMessage("error.general"), GestorIdiomas.getMessage("error"), JOptionPane.ERROR_MESSAGE);
        }

        return preparedStatement;
    }
}
